<!--业务监控详情-->
<template>
	<div class="app-container">
		<!-- 搜索条件 -->
		<yd-form class="yd-form-wraper" :model="formData" :options="formOptions" @form-init="formInited" @search="formInited">
			<template #form-btn>
				<el-button type="primary" @click="searchHandler">查询</el-button>
			</template>
		</yd-form>
		<!-- 中部饼图与趋势图 -->
		<el-row :gutter="12" style="height: 1040px; width: 100%">
			<el-col :span="12" style="height: 100%">
				<!--左侧图表-->
				<el-row :gutter="12" style="height: 45%; margin-bottom: 15px">
					<!-- 业务概况 -->
					<el-col :span="12" style="height: 100%">
						<div class="table-background-color bg-chart">
							<div class="pie-title-box">
								<div class="circle"></div>
								<div>业务概况</div>
							</div>
							<el-row style="height: 48%">
								<el-col :span="12" style="height: 100%">
									<!-- 健康度环形图表 -->
									<div style="height: 100%; width: 100%" id="healthPercentChartId"></div>
								</el-col>
								<el-col :span="12" style="height: 100%">
									<!-- 成功率环形图表 -->
									<div style="height: 100%; width: 100%" id="successPercentChartId"></div>
								</el-col>
							</el-row>
							<el-row>
								<div class="userNum">
									<div class="userNum-box">
										当前用户数：
										<span @click="go2UserOperate()" class="userNum-text text-blue">{{ userNum }}</span>
									</div>
									<div class="userNum-box">
										异常用户数：
										<span @click="go2UserOperate(1)" class="userNum-text text-red">{{ exceptionUserNum }}</span>
									</div>
								</div>
							</el-row>
							<!-- 访问量、受理量 -->
							<el-row style="height: 32%">
								<el-col :span="24" class="count-text-container">
									<div class="count-text-box">
										<el-row class="count-text-row">
											<el-col :span="3" class="count-text-cell">
												<div class="count-text-title">名称</div>
												<div class="count-text-value">
													{{ businessTableData[0].name }}
												</div>
												<div class="count-text-value">
													{{ businessTableData[1].name }}
												</div>
											</el-col>
											<el-col :span="3" class="count-text-cell">
												<div class="count-text-title">总数</div>
												<div class="count-text-value">
													{{ businessTableData[0].total || '-' }}
												</div>
												<div class="count-text-value">
													{{ businessTableData[1].total || '-' }}
												</div>
											</el-col>
											<el-col :span="3" class="count-text-cell">
												<div class="count-text-title">告警</div>
												<div class="count-text-value">
													<el-link class="text-yellow" @click="handleAlarmValJump(undefined)">{{ businessTableData[0].alarmTotal || '-' }}</el-link>
												</div>
												<div class="count-text-value">
													<el-link class="text-yellow" @click="handleAlarmValJump('1')">{{ businessTableData[1].alarmTotal || '-' }}</el-link>
												</div>
											</el-col>
											<el-col :span="3" class="count-text-cell">
												<div class="count-text-title">失败</div>
												<div class="count-text-value">
													<el-link class="text-red" @click="handleFailValJump(undefined)">{{ businessTableData[0].faileTotal || '-' }}</el-link>
												</div>
												<div class="count-text-value">
													<el-link class="text-red" @click="handleFailValJump('1')">{{ businessTableData[1].faileTotal || '-' }}</el-link>
												</div>
											</el-col>
										</el-row>
									</div>
								</el-col>
							</el-row>
						</div>
					</el-col>
					<!-- 告警类型占比 -->
					<el-col :span="12" style="height: 100%">
						<div class="table-background-color bg-chart">
							<div class="pie-title-box">
								<div class="circle"></div>
								<div>告警类型占比</div>
							</div>
							<div id="alarmTypePercenCharttId" style="height: 90%; width: 100%; margin-top: -4%"></div>
						</div>
					</el-col>
				</el-row>
				<!-- 转化率 -->
				<div style="height: 40%; margin-bottom: 15px">
					<div id="convertRateBar" class="table-background-color bg-chart p10"></div>
				</div>
				<!-- 平均 时长/服务端耗时/客户端耗时/响应时长-->
				<el-row style="height: 11%">
					<div class="table-background-color bg-chart" style="padding: 15px">
						<el-row class="avg-title-row">
							<el-col :span="6">平均处理时长</el-col>
							<el-col :span="6">平均请求传输耗时</el-col>
							<el-col :span="6">平均响应传输耗时</el-col>
							<el-col :span="6">平均响应时长</el-col>
						</el-row>
						<el-row class="avg-value-row">
							<el-col :span="6">{{ averageTableData.avgServerDealTime }}</el-col>
							<el-col :span="6">{{ averageTableData.clientAvgTranslateTime }}</el-col>
							<el-col :span="6">{{ averageTableData.serverAvgTranslateTime }}</el-col>
							<el-col :span="6">{{ averageTableData.serverAvgResponseTime }}</el-col>
						</el-row>
					</div>
				</el-row>
			</el-col>

			<!-- 健康度趋势、平均响应耗时趋势、 访问量趋势、 受理量趋势 -->
			<el-col :span="12" style="height: 100%">
				<div class="trend-container">
					<div class="table-background-color bg-chart">
						<div class="line-title-box">
							<div class="circle"></div>
							<div>健康度趋势(%)</div>
						</div>
						<div id="businessHealthTrendChartId" style="height: 80%; width: 100%"></div>
					</div>
				</div>
				<div class="trend-container">
					<div class="table-background-color bg-chart">
						<div class="line-title-box">
							<div class="circle"></div>
							<div>平均响应耗时趋势(毫秒)</div>
						</div>
						<div id="responseTimeTrendChartId" style="height: 80%; width: 100%"></div>
					</div>
				</div>
				<div class="trend-container">
					<div class="table-background-color bg-chart">
						<div class="yd-flex" style="padding-top: 15px; padding-bottom: 10px">
							<div class="line-title-box">
								<div class="circle"></div>
								<div>访问量趋势</div>
							</div>
							<div>
								<el-tooltip effect="light" :z-index="9999">
									<span style="z-index: 9999; margin-right: 15px">历史峰值：{{ reqPeek.peakValue }}</span>
									<template #content>
										<p>历史峰值：{{ reqPeek.peakValue }}</p>
										<p>发生时间：{{ reqPeek.peakStartTime }} - {{ reqPeek.peakEndTime }}</p>
									</template>
								</el-tooltip>
								<el-tooltip effect="light" :z-index="9999">
									<span style="z-index: 9999; margin-right: 15px">月平均值：{{ reqPeek.monthAvgValue }}</span>
									<template #content>
										<p>月平均值：{{ reqPeek.monthAvgValue }}</p>
										<p>发生时间：{{ reqPeek.monthStartTime }} - {{ reqPeek.monthEndTime }}</p>
									</template>
								</el-tooltip>
								<el-tooltip effect="light" :z-index="9999">
									<span style="z-index: 9999; margin-right: 15px">周平均值：{{ reqPeek.weekAvgValue }}</span>
									<template #content>
										<p>周平均值：{{ reqPeek.weekAvgValue }}</p>
										<p>发生时间：{{ reqPeek.weekStartTime }} - {{ reqPeek.weekEndTime }}</p>
									</template>
								</el-tooltip>
							</div>
						</div>

						<div id="trafficTrendChartId" style="height: 80%; width: 100%"></div>
					</div>
				</div>
				<div class="trend-container">
					<div class="table-background-color bg-chart">
						<div class="line-title-box">
							<div class="circle"></div>
							<div>受理量趋势</div>
						</div>
						<div id="acceptanceTrendChartId" style="height: 80%; width: 100%"></div>
					</div>
				</div>
			</el-col>
		</el-row>

		<!-- 业务步骤IT路径图 -->
		<div class="table-background-color bg-chart mb15">
			<div class="it-title-box">
				<div class="circle"></div>
				<div>业务步骤IT路径图</div>
			</div>
			<div v-if="noBusiItData" class="nodata-box">
				<svg-icon class-name="nodata" icon-class="nodata" style="width: 1.2rem"></svg-icon>
				<span style="font-size: 14px; margin-left: 5px">暂无数据~</span>
			</div>
			<yd-it-road-sec
				v-loading="busiRoadLoading"
				v-show="!noBusiItData"
				ref="busiItRoadRef"
				:config="{
					type: 'BusinessStep',
					canvasHeight: 360,
					noDataFlag: false,
					customOptions: busiItRoad.customOptions,
				}"
				@dblclickNode="dblclickNode"
				@dragNode="updateSegmentPositionFn"
			></yd-it-road-sec>
		</div>
		<!-- 网端详细信息列表 -->
		<div class="table-background-color bg-chart mb15">
			<div class="it-title-box">
				<div class="circle"></div>
				<div>网端详细信息列表</div>
			</div>
			<YdTable
				:formData="segmentParams"
				:tableConfig="tableConfig"
				:tableData="tableData.data"
				@sizeChangeHandler="getSegTableData"
				@currentChangeHandler="getSegTableData"
				@sortChangeHandler="getSegTableData"
			></YdTable>
		</div>

		<!-- 步骤分析 -->
		<div>
			<div class="block-title">步骤分析</div>
			<!-- <div v-if="noItData" class="nodata-box">
				<svg-icon class-name="nodata" icon-class="nodata" style="width: 1.2rem"></svg-icon>
				<span style="font-size: 14px; margin-left: 5px">暂无数据~</span>
			</div> -->
			<yd-it-road
				ref="ydItRoadRef"
				:config="{
					type: 'StepAnalysis',
					canvasHeight: 360,
					noDataFlag: false,
					customOptions: itRoad.customOptions,
				}"
				@clickNode="clickNode"
			></yd-it-road>
		</div>
		<!-- 步骤趋势分析 -->
		<div class="block-title">步骤趋势分析</div>
		<el-row style="height: 680px; width: 100%">
			<div class="table-background-color bg-chart">
				<div class="step-trend-container-first">
					<div class="line-title-box-first">
						<div class="circle"></div>
						<div>健康度趋势(%)</div>
					</div>
					<div id="processBusinessHealthTrendChartId" style="height: 80%; width: 100%"></div>
				</div>
				<div class="step-trend-container">
					<div class="line-title-box">
						<div class="circle"></div>
						<div>平均响应时长趋势(毫秒)</div>
					</div>
					<div id="processResponseTimeTrendChartId" style="height: 80%; width: 100%"></div>
				</div>
				<div class="step-trend-container">
					<div class="line-title-box">
						<div class="circle"></div>
						<div>请求量趋势</div>
					</div>
					<div id="processTrafficTrendChartId" style="height: 80%; width: 100%"></div>
				</div>
				<div class="step-trend-container">
					<div class="line-title-box">
						<div class="circle"></div>
						<div>告警量趋势</div>
					</div>
					<div id="processAlarmTrendChartId" style="height: 80%; width: 100%"></div>
				</div>
			</div>
		</el-row>
	</div>
</template>
<script setup lang="tsx">
import { ref, reactive, onMounted, onActivated, nextTick, getCurrentInstance } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import * as echarts from 'echarts';
import 'echarts-liquidfill';
import {
	getBuinessLineChartData,
	getBusinessAlarmPercent,
	getBuinessProcessAnalysis,
	getBuinessDataPercen,
	getBuinessProcessTrendData,
	getConversionRate,
	getSegmentDetailList,
	stepEndToEndRelation,
	updateSegmentPosition,
} from '@/api/bpm/business/business_monitoring_details';
import { getConfigKey } from '@/api/management/systemManage/systemConfig';

// import YdCard from '@/components/YdCard/index';
import YdItRoad from '@/components/YdItRoad/index.vue';
import YdItRoadSec from '@/components/YdItRoad/itRoadSecond.vue';
import { toDecimalFormate2, randomUUID, toDecimalFormate, simulateFormSubmit, formatGraphData } from '@/utils/common';
import { systemMonitorChartStyle, noDataOption } from '@/utils/defaultChartConfig';
import { resizeMixins } from '@/mixins/resize';
import { EdgeConfigType, GraphCustomOptionsType, GraphData } from '@/components/YdItRoad/itRoad-type';

const instance = getCurrentInstance();
const proxy = instance?.proxy;

let route = useRoute();
let router = useRouter();
let ydItRoadRef = ref<InstanceType<typeof YdItRoad>>();
let busiItRoadRef = ref<InstanceType<typeof YdItRoadSec>>();

let SystemCountChartOption = ref(null);
let processCountOption = ref(null);
let isFirstSegmentID = ref('');
//当前用户数
let userNum = ref(0);
let exceptionUserNum = ref(0);
// 折线图统一样式
let lineChartStyle = systemMonitorChartStyle();
let labelTimeArr = ref([]);
let processLabelTimeArr = ref([]);

let reqPeek = ref<anyObj>({});
// 表单项配置
const formOptions = ref<FormOptionType>([
	{
		type: 'select',
		label: '业务系统',
		prop: 'systemId',
		api: {
			name: 'queryAppSystemOptions',
			params: { isStatus: 1 },
		},
		cascaders: [
			{
				cascadersParams: 'businessCode',
				api: {
					name: 'queryBusinessOptions',
				},
			},
		],
		attrs: {
			clearable: false,
		},
	},
	{
		type: 'select',
		label: '业务名称',
		prop: 'businessCode',
		attrs: {
			clearable: false,
		},
	},
	{
		type: 'date-picker',
		label: '',
		prop: 'dateRange',
		dateType: 'datetimerange',
		// shortcutsKeys: ['last1h', 'today', 'lastDay'],
		// defaulShortcutsKey: 'lastlh',
	},
]);

// 业务概况模块中的表格数据
let businessTableData = ref([
	{
		name: '访问量',
		total: 0,
		alarmTotal: '',
		faileTotal: '',
	},
	{
		name: '受理量',
		total: 0,
		alarmTotal: '',
		faileTotal: '',
	},
]);
// 平均时长/平均请求传输耗时/平均响应传输耗时/平均响应时长表格数据
let averageTableData = reactive({
	avgServerDealTime: '0',
	clientAvgTranslateTime: '0',
	serverAvgTranslateTime: '0',
	serverAvgResponseTime: '0',
});
//查询参数
let formData = reactive<FormModelType>({});
let cloneFormData: FormModelType = {};
// 图表对象
let chart: anyObj = {
	healthPercentChart: null,
	successPercentChart: null,
	alarmTypePercentChart: null,

	businessHealthTrendChart: null,
	responseTimeTrendChart: null,
	trafficTrendChart: null,
	acceptanceTrendChart: null,

	processBusinessHealthTrendChart: null,
	processResponseTimeTrendChart: null,
	processTrafficTrendChart: null,
	processAlarmTrendChart: null,

	convertRateBar: null,
};
let noItData = ref(false);
let itRoadMode = ref('default');
// 步骤分析路径图
let itRoad = reactive<Record<string, GraphCustomOptionsType>>({
	customOptions: {
		minZoom: 1,
		maxZoom: 2,
		layout: {
			type: 'dagre',
			rankdir: 'LR',
			nodesep: 40,
			ranksep: 80,
		},
		// 默认模式
		modes: {
			defaultMode: [
				// 鼠标移入显示提示框
				{
					type: 'tooltip',
					// 是否出现，当右键菜单出现时隐藏悬浮框
					shouldBegin: (ev: any) => {
						let flag = true;
						let doms = document.getElementsByClassName('g6-contextMenu') as HTMLCollectionOf<HTMLElement>;
						for (let i = 0; i < doms.length; i++) {
							if (doms[i].style.visibility === 'visible') {
								flag = false;
							}
						}

						// 长度没有超过10个字符时隐藏悬浮框
						if (ev.item._cfg.model.stepName.length < 10) {
							flag = false;
						}
						return flag;
					},
					formatText(model: any) {
						let text = model.stepName;
						return '<span style="background-color: #ffffff; padding: 5px 10px; font-size: 14px;">' + text + '</span>';
					},
				},
			],
			editNoDragNode: [
				// 拖拽画布
				'drag-canvas',
				// 缩放画布
				'zoom-canvas',
				// 节点高亮(自定义)
				'activate-node',
				// 鼠标移入显示提示框
				{
					type: 'tooltip',
					// 是否出现，当右键菜单出现时隐藏悬浮框
					shouldBegin: (ev: any) => {
						let flag = true;
						let doms = document.getElementsByClassName('g6-contextMenu') as HTMLCollectionOf<HTMLElement>;
						for (let i = 0; i < doms.length; i++) {
							if (doms[i].style.visibility === 'visible') {
								flag = false;
							}
						}

						// 长度没有超过10个字符时隐藏悬浮框
						if (ev.item._cfg.model.stepName.length < 10) {
							flag = false;
						}
						return flag;
					},
					formatText(model: any) {
						let text = model.stepName;
						return '<span style="background-color: #ffffff; padding: 5px 10px; font-size: 14px;">' + text + '</span>';
					},
				},
			],
		},

		// 工具按钮
		toolbarObj: {
			getContent: () => {
				let outDiv = document.createElement('div');
				outDiv.style.width = '120px';
				outDiv.innerHTML = `
				<ul>
				  <li code="edit">
					<svg class="svg-icon" aria-hidden="true"  >
					  <use  id="iconEditId" xlink:href="#icon-itRoad-edit" fill="#ffffff" />
					</svg>
				  </li>
				</ul>
				`;
				return outDiv;
			},
			handleClick: (code, graph) => {
				if (code === 'edit') {
					if (itRoadMode.value === 'default') {
						itRoadMode.value = 'editNoDragNode';
						document.getElementById('iconEditId')!.setAttribute('fill', '#2beded');
					} else {
						itRoadMode.value = 'default';
						document.getElementById('iconEditId')!.setAttribute('fill', '#ffffff');
					}
					ydItRoadRef.value?.setGraphMode(itRoadMode.value);
				}
			},
		},
	},
});

// 网端详细信息列表相关
let segmentParams = reactive({
	pageSize: 10,
	pageNum: 1,
	orderByColumn: '',
	isAsc: '',
});
let tableConfig = reactive<TableConfigType>({
	columns: [
		{
			label: '关键字',
			prop: 'requestUrl',
			width: 180,
		},
		{
			label: '响应IP端口',
			prop: 'responseIp',
			sortable: true,
			formatter(row: any, val: any) {
				return val + ':' + row.responsePort;
			},
		},
		{
			label: '访问量',
			prop: 'reqCount',
			sortable: true,
		},
		{
			label: '平均处理时长',
			prop: 'avgDealTime',
			sortable: true,
			formatter(row: any, val: any) {
				return toDecimalFormate(val);
			},
		},
		{
			label: '处理时长峰值',
			prop: 'maxDealTime',
			sortable: true,
			formatter(row: any, val: any) {
				return toDecimalFormate(val);
			},
		},
		{
			label: '处理时长谷值',
			prop: 'minDealTime',
			sortable: true,
			formatter(row: any, val: any) {
				return toDecimalFormate(val);
			},
		},
		{
			label: '平均网络传输时长',
			prop: 'avgTranslateTime',
			sortable: true,
			formatter(row: any, val: any) {
				return toDecimalFormate(val);
			},
		},
		{
			label: '平均服务端耗时',
			prop: 'serverAvgResponseTime',
			sortable: true,
			formatter(row: any, val: any) {
				return toDecimalFormate(val);
			},
		},
		{
			label: '告警访问量',
			prop: 'alarmReqCount',
			sortable: true,
			operation: [
				{
					rowKey: 'alarmReqCount',
					color: '#ff9a0c',
					handler: (scope: any) => {
						jumpToBaseAlarm(formData, '');
					},
				},
			],
		},
		{
			label: '失败数',
			prop: 'failReqCount',
			sortable: true,
			operation: [
				{
					rowKey: 'failReqCount',
					color: '#fe5578',
					handler: (scope: any) => {
						jumpToBaseAlarm(formData, 0);
					},
				},
			],
		},
		{
			label: '健康度',
			prop: 'healthyRate',
			sortable: true,
			renderXss: (row: any, val: any) => {
				if (val === null || val === '' || val === undefined) {
					return '-';
				} else {
					if (val >= 90) {
						return <span style="color: #30B08F">{val + '%'}</span>;
					} else if (val >= 70) {
						return <span style="color: #FEC171">{val + '%'}</span>;
					} else {
						return <span style="color: #C03639">{val + '%'}</span>;
					}
				}
			},
		},
		{
			label: '操作',
			prop: '',
			operation: [
				{
					text: '提包分析',
					handler: (scope: any) => {
						handlePackageAnalysis(scope.row);
					},
				},
			],
			hide: false,
			width: 100,
		},
	],
	pagination: {
		pageNum: 1,
	},
	loading: false,
});
let tableData = reactive({
	data: [],
});
let noBusiItData = ref(false);
let busiRoadLoading = ref(false);
let busiItMode = ref('default');
// 业务步骤IT路径图
let busiItRoad = reactive({
	customOptions: {
		layout: {
			type: 'dagre',
			rankdir: 'LR',
			nodesep: 40,
			ranksep: 80,
		},
		// 默认模式
		defaultMode: [
			// 节点高亮(自定义)
			'activate-node',
		],
		// 工具按钮
		toolbarObj: {
			getContent: () => {
				let outDiv = document.createElement('div');
				outDiv.style.width = '120px';
				outDiv.innerHTML = `
					<ul>
					  <li code="edit">
						<svg class="svg-icon" aria-hidden="true"  >
						  <use  id="busiIconEditId" xlink:href="#icon-itRoad-edit" fill="#ffffff" />
						</svg>
					  </li>
					</ul>`;
				return outDiv;
			},
			handleClick: (code: any, graph: any) => {
				if (code === 'edit') {
					if (busiItMode.value === 'default') {
						busiItMode.value = 'edit';
						document.getElementById('busiIconEditId')?.setAttribute('fill', '#2beded');
					} else {
						busiItMode.value = 'default';
						document.getElementById('busiIconEditId')?.setAttribute('fill', '#ffffff');
					}
					busiItRoadRef.value?.setGraphMode(busiItMode.value);
				}
			},
		},
	},
});
let currentSegId = ref('');

resizeMixins(chart);

initQuery(route.query, formData);

onMounted(() => {
	initChart();
});

// 格式化传过来的参数
function initQuery(query: anyObj, formData: FormModelType) {
	try {
		let data = JSON.parse(query.data);
		for (let key in data) {
			formData[key] = data[key];
		}
	} catch {
		for (let key in query) {
			formData[key] = query[key];
		}
	}
	// console.log('fomrData', formData);
}

/**
 * 初始化页面信息
 */
function formInited() {
	initQuery(route.query, formData);
	searchHandler();
	console.log('formniit-----------', formData);
}

/**
 * 初始化图表对象
 */
function initChart() {
	chart.healthPercentChart = echarts.init(document.getElementById('healthPercentChartId') as HTMLElement);
	chart.successPercentChart = echarts.init(document.getElementById('successPercentChartId') as HTMLElement);
	chart.alarmTypePercentChart = echarts.init(document.getElementById('alarmTypePercenCharttId') as HTMLElement);
	chart.businessHealthTrendChart = echarts.init(document.getElementById('businessHealthTrendChartId') as HTMLElement);
	chart.responseTimeTrendChart = echarts.init(document.getElementById('responseTimeTrendChartId') as HTMLElement);
	chart.trafficTrendChart = echarts.init(document.getElementById('trafficTrendChartId') as HTMLElement);
	chart.acceptanceTrendChart = echarts.init(document.getElementById('acceptanceTrendChartId') as HTMLElement);
	chart.processBusinessHealthTrendChart = echarts.init(document.getElementById('processBusinessHealthTrendChartId') as HTMLElement);
	chart.processResponseTimeTrendChart = echarts.init(document.getElementById('processResponseTimeTrendChartId') as HTMLElement);
	chart.processTrafficTrendChart = echarts.init(document.getElementById('processTrafficTrendChartId') as HTMLElement);
	chart.processAlarmTrendChart = echarts.init(document.getElementById('processAlarmTrendChartId') as HTMLElement);
	chart.convertRateBar = echarts.init(document.getElementById('convertRateBar') as HTMLElement);
}
//重新设置图表宽高
// function chartResize() {
// 	Object.keys(chart).forEach((key) => {
// 		chart[key].resize();
// 	});
// }

/**
 * 初始化页面信息
 */
function getAllData() {
	// 没有业务不请求
	if (!formData.businessCode) {
		renderNoData();
		return false;
	}
	queryBusinessData();
	handlerChartSearch(0);
	handlerSearchLineChart();
	handlerSearchProcessLineChart();
	renderStepOverviewRoad();
	getConverRateBar();
	renderBusiRoad();
}

function renderNoData() {
	noDataOption(chart.healthPercentChart, {
		textStyle: { color: '#fff' },
	});
	noDataOption(chart.successPercentChart, {
		textStyle: { color: '#fff' },
	});
	noDataOption(chart.alarmTypePercentChart, {
		textStyle: { color: '#ffffff' },
	});
	noDataOption(chart.convertRateBar, {
		textStyle: { color: '#ffffff' },
	});
	noDataOption(chart.businessHealthTrendChart, {
		textStyle: { color: '#ffffff' },
	});
	noDataOption(chart.responseTimeTrendChart, {
		textStyle: { color: '#ffffff' },
	});
	noDataOption(chart.trafficTrendChart, {
		textStyle: { color: '#ffffff' },
	});
	noDataOption(chart.acceptanceTrendChart, {
		textStyle: { color: '#ffffff' },
	});

	noDataOption(chart.processBusinessHealthTrendChart, {
		textStyle: { color: '#ffffff' },
	});
	noDataOption(chart.processResponseTimeTrendChart, {
		textStyle: { color: '#ffffff' },
	});
	noDataOption(chart.processTrafficTrendChart, {
		textStyle: { color: '#ffffff' },
	});
	noDataOption(chart.processAlarmTrendChart, {
		textStyle: { color: '#ffffff' },
	});
	noBusiItData.value = true;
}
/**
 * 搜索按钮
 */
function searchHandler() {
	formData.pageNum = 1;
	getAllData();
}
// 查询业务概况的相关数据
function queryBusinessData() {
	// 没有业务不请求

	getBuinessDataPercen(formData).then((res: ApiResponse) => {
		// 清空图表
		chart.healthPercentChart.clear();
		chart.successPercentChart.clear();
		if (res.code === 8001) {
			return;
		} else if (res.code !== 0) {
			proxy?.$message.warning(res.msg);
			noDataOption(chart.healthPercentChart, {
				textStyle: { color: '#fff' },
			});
			noDataOption(chart.successPercentChart, {
				textStyle: { color: '#fff' },
			});
			userNum.value = 0;
			businessTableData.value = [
				{
					name: '访问量',
					total: 0,
					alarmTotal: '',
					faileTotal: '',
				},
				{
					name: '受理量',
					total: 0,
					alarmTotal: '',
					faileTotal: '',
				},
			];
			averageTableData = {
				avgServerDealTime: '0s',
				clientAvgTranslateTime: '0s',
				serverAvgTranslateTime: '0s',
				serverAvgResponseTime: '0s',
			};
			return;
		}
		let data = res.data;
		// if (res.cycleTableMsg) {
		// 	proxy?.$message.warning(res.cycleTableMsg);
		// }
		// 无数据时显示
		if (!data) {
			noDataOption(chart.healthPercentChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.successPercentChart, {
				textStyle: { color: '#ffffff' },
			});
		} else {
			if (!data.healthRate) {
				noDataOption(chart.healthPercentChart, {
					textStyle: { color: '#ffffff' },
				});
			} else {
				healthPercentChartSearch(data.healthRate * 100);
			}
			if (!data.successRate) {
				noDataOption(chart.successPercentChart, {
					textStyle: { color: '#ffffff' },
				});
			} else {
				successPercentChartSearch(data.successRate * 100);
			}
		}
		userNum.value = data.userNum || 0;
		exceptionUserNum.value = data.exceptionUserNum || 0;
		// 回填业务概况模块下面表格的数据
		businessTableData.value[0].total = data.visitCount;
		businessTableData.value[0].alarmTotal = data.alarmVisitCount;
		businessTableData.value[0].faileTotal = data.failVisitCount;
		businessTableData.value[1].total = data.completeVisitCount;
		businessTableData.value[1].alarmTotal = data.alarmCompleteVisitCount; // 缺字段，暂时留空
		businessTableData.value[1].faileTotal = data.failCompleteVisitCount;

		// 回填平均 时长/服务端耗时/客户端耗时/响应时长表格数据
		averageTableData.avgServerDealTime = data.avgServerDealTime == undefined ? 0 + 's' : toDecimalFormate2(data.avgServerDealTime, 'wm');
		averageTableData.clientAvgTranslateTime =
			data.clientAvgTranslateTime == undefined ? 0 + 's' : toDecimalFormate2(data.clientAvgTranslateTime, 'wm');
		averageTableData.serverAvgTranslateTime =
			data.serverAvgTranslateTime == undefined ? 0 + 's' : toDecimalFormate2(data.serverAvgTranslateTime, 'wm');
		averageTableData.serverAvgResponseTime = data.serverAvgResponseTime == undefined ? 0 + 's' : toDecimalFormate2(data.serverAvgResponseTime, 'wm');
	});
}
// 渲染健康度环形图表
function healthPercentChartSearch(parcenData: any) {
	let chartIns = chart.healthPercentChart;
	// 有数据
	chartIns.setOption({
		title: {
			text: (parcenData == 100 ? Number(parcenData).toFixed(0) : Number(parcenData).toFixed(2)) + '{a|%}',
			textStyle: {
				fontSize: 22,
				fontFamily: 'Microsoft Yahei',
				fontWeight: 'normal',
				color: '#ffffff',
				rich: {
					a: {
						fontSize: 24,
					},
				},
			},
			x: 'center',
			y: '40%',
		},
		graphic: [
			{
				type: 'group',
				left: 'center',
				top: '62%',
				children: [
					{
						type: 'text',
						z: 100,
						left: '10',
						top: 'middle',
						style: {
							fill: '#ffffff',
							text: '健康度',
							fontSize: 16,
						},
					},
				],
			},
		],
		series: [
			{
				type: 'liquidFill',
				radius: '70%',
				center: ['50%', '50%'],
				data: [parcenData / 100, parcenData / 100],
				backgroundStyle: {
					color: 'rgba(134, 228, 245, 0.2)',
				},
				outline: {
					borderDistance: 0,
					itemStyle: {
						borderWidth: 12,
						borderColor: {
							type: 'linear',
							x: 0,
							y: 0,
							x2: 0,
							y2: 1,
							colorStops: [
								{
									offset: 0,
									color: '#427ed7',
								},
								{
									offset: 0.5,
									color: '#66b5e7',
								},
								{
									offset: 1,
									color: '#85e2f5',
								},
							],
							globalCoord: false,
						},
					},
				},
				// 水波浪的颜色及透明度
				color: ['#49a5bf', '#34fdff'],
				itemStyle: {
					opacity: 0.8,
				},
				label: {
					normal: {
						formatter: '',
					},
				},
			},
		],
	});
}
// 渲染成功率环形图表
function successPercentChartSearch(parcenData: any) {
	let chartIns = chart.successPercentChart;
	// 有数据
	chartIns.setOption({
		// 全局字体样式
		textStyle: {
			color: '#00ffff',
		},
		// 调色盘
		color: ['#ff9a0c', '#00ffff', '#6d51f5', '#fe5578', '#ff7d4f'],
		tooltip: {
			trigger: 'item',
		},
		title: {
			text: (parcenData == 100 ? Number(parcenData).toFixed(0) : Number(parcenData).toFixed(2)) + '%',
			textStyle: {
				fontSize: 22,
				fontFamily: 'Microsoft Yahei',
				fontWeight: 'normal',
				color: '#ffffff',
			},
			x: 'center',
			y: '40%',
		},
		graphic: [
			{
				type: 'group',
				left: 'center',
				top: '60%',
				children: [
					{
						type: 'text',
						z: 100,
						left: '10',
						top: 'middle',
						style: {
							fill: '#2beded',
							text: '成功率',
							fontSize: 16,
						},
					},
				],
			},
		],
		series: [
			{
				type: 'pie',
				radius: ['60%', '75%'],
				avoidLabelOverlap: false,
				hoverAnimation: false,
				label: {
					show: false,
				},
				labelLine: {
					show: false,
				},
				tooltip: {
					formatter: '{b}：{d}%',
				},
				data: [
					{
						value: parseFloat(parcenData),
						name: '成功率',
						itemStyle: {
							normal: {
								color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
									{ offset: 0, color: '#0af6ff' },
									{ offset: 1, color: '#6d9afe' },
								]),
							},
							emphasis: {
								color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
									{ offset: 0, color: '#0af6ff' },
									{ offset: 1, color: '#6d9afe' },
								]),
							},
						},
					},
					{
						value: 100 - parseFloat(parcenData),
						name: '失败率',
						itemStyle: {
							normal: {
								color: '#d8d8d833',
							},
							emphasis: {
								color: '#d8d8d833',
							},
						},
					},
				],
			},
		],
	});
}
// 获取告警类型占比饼图数据
function handlerChartSearch(percentType: any) {
	getBusinessAlarmPercent({
		...formData,
		percentType: percentType,
	}).then((res: ApiResponse) => {
		if (res.code === 8001) {
			return;
		} else if (res.code !== 0) {
			proxy?.$message.warning(res.msg);
			noDataOption(chart.alarmTypePercentChart, {
				textStyle: { color: '#ffffff' },
			});
			return;
		}
		// if (res.cycleTableMsg) {
		// 	proxy?.$message.warning(res.cycleTableMsg);
		// }
		// 有数据
		let valueArr: any[] = [];
		let data = res.data;
		chart.alarmTypePercentChart.clear();
		if (!data || data.length <= 0) {
			// 无数据
			noDataOption(chart.alarmTypePercentChart, {
				textStyle: { color: '#ffffff', formatter: '暂无告警数据~' },
			});
		} else {
			data.forEach((d: anyObj) => {
				valueArr.push({
					name: d.alarmTypeName,
					value: d.alarmCount,
					alarmTypeId: d.alarmTypeId,
				});
			});
			renderAlarmTypeProportionChart('alarmTypePercentChart', valueArr);
		}
	});
}
// 渲染告警类型环形图
function renderAlarmTypeProportionChart(alarmPercent: any, valueArr: any) {
	let chartIns = chart[alarmPercent];
	// 有数据
	chartIns.setOption({
		// 调色盘
		color: ['#fe5578', '#ff7d4f', '#6f81f7', '#1dc69d', '#00ffff', '#e5ba43', '#25b2ff', '#13eecc'],
		// 图例
		legend: {
			top: 'bottom',
			// 间距
			itemGap: 15,
			textStyle: {
				color: '#ffffff',
			},
		},
		// 悬浮提示
		tooltip: {
			trigger: 'item',
			formatter: '{b}：{d}%',
		},
		series: [
			{
				name: '占比',
				type: 'pie',
				radius: ['30%', '45%'],
				center: ['50%', '35%'],
				avoidLabelOverlap: true,
				// 标签文本
				label: {
					formatter: function (params: anyObj) {
						let percent = params.percent + '%';
						let paramsName = params.name;
						let newParamsName = '';
						let paramsNameNumber = params.length;
						let provideNumber = 4;
						let rowNumber = Math.ceil(paramsNameNumber / provideNumber);
						if (paramsNameNumber > provideNumber) {
							for (let p = 0; p < rowNumber; p++) {
								let tempStr = '';
								let start = p * provideNumber;
								let end = start + provideNumber;
								if (p == rowNumber - 1) {
									tempStr = params.substring(start, paramsNameNumber);
								} else {
									tempStr = params.substring(start, end) + '\n';
								}
								newParamsName += tempStr;
							}
						} else {
							newParamsName = paramsName;
						}
						return newParamsName + '\n' + percent;
					},
				},
				// 标签线
				labelLine: {
					length: 10,
					length2: 10,
					lineStyle: {
						type: 'dashed',
					},
				},
				// 高亮状态
				emphasis: {
					label: {
						show: true,
						fontSize: '14',
						fontWeight: 'bold',
					},
				},
				data: valueArr,
			},
		],
	});
}
//格式化横坐标时间值
// function formatTime(timeStr) {
// 	return timeStr.substring(11, 16);
// }
// 转化率柱状图
function getConverRateBar() {
	chart.convertRateBar.clear();
	getConversionRate(formData).then((res: ApiResponse) => {
		if (res.code === 8001) {
			return;
		} else if (res.code !== 0) {
			proxy?.$message.warning(res.msg);
			noDataOption(chart.convertRateBar, {
				textStyle: { color: '#ffffff' },
			});
			return;
		}
		// if (res.cycleTableMsg) {
		// 	proxy?.$message.warning(res.cycleTableMsg);
		// }
		let data = res.data.data;
		if (!data || data.length <= 0) {
			// 无数据
			noDataOption(chart.convertRateBar, {
				textStyle: { color: '#ffffff' },
			});
		} else {
			let labelArr: any[] = [],
				valArr: any[] = [];
			if (data.length > 1) {
				data.forEach((d: any, index: number) => {
					labelArr.push(d.stepName + '-' + (index + 1));
					valArr.push(d.visitCount);
					labelArr.push('相对转化率' + d.conversionRate + '%');
					valArr.push(0);
				});
				labelArr.pop();
				valArr.pop();
			} else {
				labelArr.push(data[0].stepName);
				valArr.push(data[0].visitCount);
			}
			chart.convertRateBar.setOption({
				color: ['#09eef7', '#ff7d4f', '#6f81f7', '#1dc69d', '#00ffff', '#e5ba43', '#25b2ff', '#13eecc'],
				textStyle: {
					color: '#FFFFFF',
				},
				title: {
					text: '总转化率' + res.data.totalConversionRate + '%',
					textStyle: {
						color: '#FFFFFF',
					},
				},
				tooltip: {
					formatter: function (param: any) {
						let label =
							'访问量<br/>' +
							'<span style="display:inline-block;width:10px;height:10px;background:' +
							param.color +
							';margin-right:5px;border-radius:50%;}"></span><span style="margin-right:15px;display:inline-block;">' +
							param.name +
							'</span> ' +
							param.value;
						return label;
					},
				},
				grid: {
					containLabel: true,
					left: 10,
					bottom: 10,
				},
				xAxis: {
					type: 'value',
					axisLine: {
						show: false,
					},
					axisTick: {
						show: false,
					},
				},
				yAxis: {
					type: 'category',
					data: labelArr,
					inverse: true,
					axisLine: {
						lineStyle: {
							color: '#ffffff',
							opacity: 0.3,
						},
					},
				},
				series: [
					{
						name: '访问量',
						type: 'bar',
						barMaxWidth: 20,
						data: valArr,
					},
				],
			});
		}
	});
}
// 查询并渲染业务步骤IT路径图
function renderBusiRoad() {
	busiRoadLoading.value = true;
	stepEndToEndRelation({
		systemId: formData.systemId,
		businessCode: formData.businessCode,
		startTime: formData.startTime,
		endTime: formData.endTime,
	}).then((res: ApiResponse) => {
		busiRoadLoading.value = false;
		tableConfig.loading = false;
		let d: GraphData = {
			nodes: [],
			edges: [],
		};
		if (res.code !== 0 || !res.data || res.data.length === 0) {
			noBusiItData.value = true;
			busiItRoadRef.value?.loadItRoadData(d);
			tableData.data = [];
			tableConfig.pagination!.total = 0;
			return;
		}
		console.log('d', d);
		noBusiItData.value = false;

		let isSavePos = true; //是否保存了节点的位置
		formatGraphData(res.data, 'id');
		// 将数据处理成graph需要的格式
		function formatGraphData(arr: any[], idKey: string) {
			arr.forEach((node: any) => {
				if (node.locationX) {
					// 采用自定义布局
					isSavePos = false;
					busiItRoadRef.value?.setLayout({
						type: 'BusinessStepLayout',
					});
				}

				node[idKey] = node[idKey] + '';
				let index = d.nodes.findIndex((n) => n[idKey] === node[idKey]);
				if (index === -1) {
					// 没有的节点才加进去
					node.x = node.locationX;
					node.y = node.locationY;
					d.nodes.push(node);
				}
				if (node.childNodes instanceof Array) {
					node.childNodes.forEach((subNode: any) => {
						d.edges.push({
							source: node[idKey] + '',
							target: subNode[idKey] + '',
						});
					});
					formatGraphData(node.childNodes, idKey);
				}
			});
		}
		// 渲染it路劲图
		busiItRoadRef.value?.loadItRoadData(d);

		// 如果节点的locationX不存在则；保存网端位置
		if (isSavePos) {
			let nodes = busiItRoadRef.value?.getAllNodes();
			nodes.forEach((node: any) => {
				let model = node.getModel();
				updateSegmentPositionFn(null, {
					segmentId: model.id,
					locationX: model.x,
					locationY: model.y,
				});
			});
		}

		if (d.nodes[0]) {
			isFirstSegmentID.value = d.nodes[0].id;
		}

		if (d.nodes.length > 0) {
			let segId = undefined;
			for (let k of d.nodes) {
				if (k.reqCount > 0) {
					segId = k.id;
					break;
				}
			}
			if (segId != undefined) {
				// 将第一个请求量不为零的节点设置为当前节点
				currentSegId.value = segId;
				getSegTableData();
			} else {
				tableConfig.loading = false;
				tableData.data = [];
				tableConfig.pagination!.total = 0;
			}
		}
	});
}
// 双击业务步骤IT路径图节点，联动网端详细信息列表
function dblclickNode(ev: any) {
	let nodes = busiItRoadRef.value?.getAllNodes();
	nodes.forEach((node: any) => {
		let nodeModel = JSON.parse(JSON.stringify(node.getModel()));
		if (ev.item.getModel().id === nodeModel.id) {
			nodeModel.style.fill = '#1c2d46';
			node.update(nodeModel);
		} else {
			nodeModel.style.fill = '';
			node.update(nodeModel);
		}
	});
	// 渲染图表
	if (ev.item._cfg.type === 'node') {
		currentSegId.value = ev.item.getModel().id;
		getSegTableData();
	}
}
// 拖拽节点保存坐标
function updateSegmentPositionFn(ev: any, model: any) {
	// 编辑模式启动情况下才更新网端位置
	if (busiItMode.value === 'edit' || model) {
		let segmentPos = model || {
			segmentId: ev.item.getModel().id,
			locationX: ev.item.getModel().x,
			locationY: ev.item.getModel().y,
		};
		segmentPos.systemId = formData.systemId;
		if (segmentPos.locationX) {
			updateSegmentPosition(segmentPos).then(() => {});
		}
	}
}
// 查询业务量相关趋势折线图
function handlerSearchLineChart() {
	let reqData = formData;
	getBuinessLineChartData(reqData).then((res: ApiResponse) => {
		if (res.code === 8001) {
			return;
		} else if (res.code !== 0) {
			proxy?.$message.warning(res.msg);
			noDataOption(chart.businessHealthTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.responseTimeTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.trafficTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.acceptanceTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			return;
		}
		// if (res.cycleTableMsg) {
		// 	proxy?.$message.warning(res.cycleTableMsg);
		// }
		let resData = res.data.trendData;
		// 无数据
		if (!resData || resData.resLabelTimeArr.length <= 0) {
			noDataOption(chart.businessHealthTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.responseTimeTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.trafficTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.acceptanceTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			return;
		}
		reqPeek.value = resData.resFieldMap?.avgAndPeakVo || {};
		for (let key in reqPeek.value) {
			if (reqPeek.value[key] === null || reqPeek.value[key] === 'null') {
				reqPeek.value[key] = 0;
			}
		}
		console.log('reqPeek.value', reqPeek.value);
		labelTimeArr.value = resData.resLabelTimeArr;
		let healthRateCount = resData.resFieldMap.healthRateList;
		let responseTimeCount = resData.resFieldMap.avgServerResponseTime.map((t: any) => t / 1000);
		let mResAlarmCount = resData.resFieldMap.visitCountList;
		let trafficCount = resData.resFieldMap.completeVisitCountList;
		// 渲染业务各量趋势图
		renderSystemCountChart('健康度趋势', 'businessHealthTrendChart', resData.resPointTimeRangeArr, healthRateCount, 'rgb(40,238,239)');
		renderSystemCountChart('平均响应耗时趋势', 'responseTimeTrendChart', resData.resPointTimeRangeArr, responseTimeCount, 'rgb(255,154,12)');
		renderSystemCountChart('访问量趋势', 'trafficTrendChart', resData.resPointTimeRangeArr, mResAlarmCount, 'rgb(30,199,154)');
		renderSystemCountChart('受理量趋势', 'acceptanceTrendChart', resData.resPointTimeRangeArr, trafficCount, 'rgb(109,84,242)');
		//图表联动
		echarts.connect([chart.businessHealthTrendChart, chart.responseTimeTrendChart, chart.trafficTrendChart, chart.acceptanceTrendChart]);
	});
}
// 渲染业务量相关趋势折线图
function renderSystemCountChart(title: string, trendType: string, tooltipArr: any, valueArr: any, seriesColor: any) {
	let chartIns = chart[trendType];
	chartIns.clear();
	if (valueArr.length <= 0) {
		noDataOption(chartIns, {
			textStyle: { color: '#ffffff' },
		});
		return;
	}
	chartIns.setOption({
		textStyle: {
			color: '#ffffff',
		},
		// 提示框
		tooltip: {
			trigger: 'axis',
			formatter: function (params: any) {
				let label = tooltipArr[params[0].dataIndex][0] + '～' + tooltipArr[params[0].dataIndex][1] + '<br/>';
				params.forEach((item: any, index: number) => {
					label +=
						'<i style="display:inline-block;width:10px;height:10px;background:' +
						item.color +
						';margin-right:5px;border-radius:50%;}"></i><span style="width:90px;display:inline-block;">' +
						item.seriesName +
						'</span> ' +
						item.value;
				});
				if (trendType == 'businessHealthTrendChart') {
					label += '%';
				}
				if (trendType == 'responseTimeTrendChart') {
					let tiplabel = tooltipArr[params[0].dataIndex][0] + '～' + tooltipArr[params[0].dataIndex][1] + '<br/>';
					params.forEach((item: any, index: any) => {
						tiplabel +=
							'<i style="display:inline-block;width:10px;height:10px;background:' +
							item.color +
							';margin-right:5px;border-radius:50%;}"></i><span style="width:110px;display:inline-block;">' +
							item.seriesName +
							'</span> ' +
							toDecimalFormate(item.value);
					});
					return tiplabel;
				}
				return label;
			},
		},
		// 坐标系
		grid: {
			containLabel: true,
			x: 20,
			x2: 20,
			y: 8,
			y2: 3,
		},
		xAxis: {
			type: 'category',
			data: labelTimeArr.value,
			...lineChartStyle.xAxisStyle,
		},
		yAxis: {
			type: 'value',
			splitNumber: 5,
			// minInterval: 1,
			axisLabel: {
				margin: 5,
			},
			max: function () {
				if (trendType == 'businessHealthTrendChart') {
					return 100;
				}
			},
			...lineChartStyle.yAxisStyle,
		},
		series: [
			{
				name: title,
				data: valueArr,
				type: 'line',
				symbol: 'none',
				itemStyle: {
					color: seriesColor,
				},
				// 填充区域
				areaStyle: {
					color: {
						type: 'linear',
						x: 0,
						x2: 0,
						y: 0,
						y2: 1,
						colorStops: [
							{
								offset: 0,
								color: 'rgba(' + seriesColor.substring(seriesColor.indexOf('(') + 1, seriesColor.indexOf(')')) + ',0.4)',
							},
							{
								offset: 1,
								color: 'rgba(' + seriesColor.substring(seriesColor.indexOf('(') + 1, seriesColor.indexOf(')')) + ',0)',
							},
						],
					},
				},
			},
		],
	});
}
// 查询网端详细信息列表
function getSegTableData() {
	tableConfig.loading = true;
	let param = JSON.parse(JSON.stringify(formData));
	if (isFirstSegmentID.value != currentSegId.value) {
		param.businessCode = null;
	}
	getSegmentDetailList({
		...param,
		...segmentParams,
		segmentId: currentSegId.value,
	}).then((res: ApiResponse) => {
		tableConfig.loading = false;
		if (res.code !== 0) {
			proxy?.$message.warning(res.msg);
			return;
		}
		tableData.data = res.data.data;
		// tableData.total = res.data.total;
		tableConfig.pagination!.total = res.data.total;
		// debugger
	});
}
// 查询并渲染步骤总览路径图
function renderStepOverviewRoad() {
	getBuinessProcessAnalysis(formData).then((res: ApiResponse) => {
		let d: GraphData = {
			nodes: [],
			edges: [],
		};

		if (res.code !== 0 || !res.data.data || res.data.data.length == 0) {
			// 无数据
			noItData.value = true;
			ydItRoadRef.value?.loadItRoadData(d);
			return;
		}
		noItData.value = false;
		let isSavePos = true;
		let idArr: any[] = [];
		res.data.data.forEach((sitVo: any) => {
			// 采用自定义布局
			isSavePos = false;
			ydItRoadRef.value?.setLayout({
				type: 'stepAnalysisLayout',
			});
			let id = 'step-' + randomUUID();
			idArr.push(id);
			d.nodes.push({
				id: id,
				stepName: sitVo.stepName,
				reqCount: sitVo.reqCount,
				failCount: sitVo.failCount,
				failRate: sitVo.failRate + '%',
				alarmCount: sitVo.alarmNum,
				alarmNum: sitVo.alarmCount,
				healthRate: sitVo.healthRate + '%',
				stepCode: sitVo.stepCode,
				systemId: formData.systemId,
				businessCode: formData.businessCode,
			});
		});
		// 连线
		idArr.forEach((id: any, index) => {
			if (index < idArr.length - 1) {
				let e: EdgeConfigType = {
					source: idArr[index],
					target: idArr[index + 1],
				};
				if ((index + 1) % 8 === 0) {
					// 下
					e.sourceAnchor = 3;
					e.targetAnchor = 2;
					e.style = {
						endArrow: {
							path: 'M 0,0 L 5,-10 M 0,0 L -5,-10',
						},
					};
				} else if (Math.ceil((index + 1) / 8) % 2 === 0) {
					// 左
					e.sourceAnchor = 0;
					e.targetAnchor = 1;
				} else {
					// 右
					e.sourceAnchor = 1;
					e.targetAnchor = 0;
				}
				d.edges.push(e);
			}
		});
		// 重新设置画布宽高
		ydItRoadRef.value?.graph.changeSize(ydItRoadRef.value?.graph.getWidth(), Math.ceil(d.nodes.length / 8) * 180);
		ydItRoadRef.value?.loadItRoadData(d);
	});
}
// 查询步骤量相关趋势图
function handlerSearchProcessLineChart() {
	let reqData = formData;
	getBuinessProcessTrendData(reqData).then((res) => {
		if (res.code === 8001) {
			return;
		} else if (res.code !== 0) {
			proxy?.$message.warning(res.msg);
			noDataOption(chart.processBusinessHealthTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.processResponseTimeTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.processTrafficTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.processAlarmTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			return;
		}
		// if (res.cycleTableMsg) {
		// 	proxy?.$message.warning(res.cycleTableMsg);
		// }
		let resData = res.data.trendData;
		// 无数据
		if (!resData || resData.resLabelTimeArr.length <= 0) {
			noDataOption(chart.processBusinessHealthTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.processResponseTimeTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.processTrafficTrendChart, {
				textStyle: { color: '#ffffff' },
			});
			noDataOption(chart.processAlarmTrendChart, {
				textStyle: { color: '#ffffff', formatter: '暂无告警数据~' },
			});
			return;
		}
		processLabelTimeArr.value = resData.resLabelTimeArr;
		let healthSeries: any[] = [],
			responseTimeSeries: any[] = [],
			trafficSeries: any[] = [],
			alarmSeries: any[] = [];

		resData.stepNameList.forEach((item: any, index: number) => {
			healthSeries.push({
				data: resData.resFieldMap.healthRateList[index],
				name: item,
				type: 'line',
				symbolSize: 3,
			});
			responseTimeSeries.push({
				data: resData.resFieldMap.avgServerResponseTimeList[index].map((t) => t / 1000),
				name: item,
				type: 'line',
				symbolSize: 3,
			});
			trafficSeries.push({
				data: resData.resFieldMap.reqCountList[index],
				name: item,
				type: 'line',
				symbolSize: 3,
			});
			alarmSeries.push({
				data: resData.resFieldMap.alarmCountList[index],
				name: item,
				type: 'line',
				symbolSize: 3,
			});
		});

		// 渲染各量趋势图
		renderProcessCountChart('健康度趋势', 'processBusinessHealthTrendChart', resData.resPointTimeRangeArr, healthSeries, true, 1);
		renderProcessCountChart('平均响应时长趋势', 'processResponseTimeTrendChart', resData.resPointTimeRangeArr, responseTimeSeries, false, 2);
		renderProcessCountChart('请求量趋势', 'processTrafficTrendChart', resData.resPointTimeRangeArr, trafficSeries, false, 3);
		renderProcessCountChart('告警量趋势', 'processAlarmTrendChart', resData.resPointTimeRangeArr, alarmSeries, false, 4);
		//图表联动
		echarts.connect([
			chart.processBusinessHealthTrendChart,
			chart.processResponseTimeTrendChart,
			chart.processTrafficTrendChart,
			chart.processAlarmTrendChart,
		]);
	});
}
// 渲染步骤相关趋势折线图
function renderProcessCountChart(title: string, trendType: string, tooltipArr: any, series: any, showLegend: any, orderFlag: any) {
	let chartIns = chart[trendType];
	chartIns.clear();
	chartIns.setOption({
		...lineChartStyle.common,
		legend: {
			show: showLegend,
			right: '2%',
			top: '0%',
			textStyle: {
				color: '#ffffff',
			},
		},
		// 提示框
		tooltip: {
			trigger: 'axis',
			position: function (point: any, params: any, dom: any, rect: any, size: any) {
				if (series.length > 4) {
					if (point[0] > size.viewSize[0] - size.contentSize[0]) {
						// 最右居左
						return [point[0] - size.contentSize[0], 10];
					}
					if (point[0] < size.contentSize[0]) {
						// 最左居右
						return [point[0], 10];
					}
					if (orderFlag == 2 || orderFlag == 4) {
						// 2 4 居左, 1 3 居右
						return [point[0] - size.contentSize[0], 10];
					} else {
						return [point[0], 10];
					}
				}
			},
			formatter: function (params: any) {
				if (trendType == 'processBusinessHealthTrendChart') {
					let healthLabel = tooltipArr[params[0].dataIndex][0] + '～' + tooltipArr[params[0].dataIndex][1] + '<br/>';
					params.forEach((item: any, index: any) => {
						healthLabel +=
							'<i style="display:inline-block;width:10px;height:10px;background:' +
							item.color +
							';margin-right:5px;border-radius:50%;}"></i><span style="margin-right:15px;display:inline-block;">' +
							item.seriesName +
							'</span> ' +
							item.value +
							'%<br/>';
					});
					return healthLabel;
				}
				if (trendType == 'processResponseTimeTrendChart') {
					let tiplabel = tooltipArr[params[0].dataIndex][0] + '～' + tooltipArr[params[0].dataIndex][1] + '<br/>';
					params.forEach((item: any, index: any) => {
						tiplabel +=
							'<i style="display:inline-block;width:10px;height:10px;background:' +
							item.color +
							';margin-right:5px;border-radius:50%;}"></i><span style="margin-right:15px;display:inline-block;">' +
							item.seriesName +
							'</span> ' +
							toDecimalFormate(item.value) +
							'<br/>';
					});
					return tiplabel;
				}
				let label = tooltipArr[params[0].dataIndex][0] + '～' + tooltipArr[params[0].dataIndex][1] + '<br/>';
				params.forEach((item: any, index: any) => {
					label +=
						'<i style="display:inline-block;width:10px;height:10px;background:' +
						item.color +
						';margin-right:5px;border-radius:50%;}"></i><span style="margin-right:15px;display:inline-block;">' +
						item.seriesName +
						'</span> ' +
						item.value +
						'<br/>';
				});
				return label;
			},
		},
		// 坐标系
		grid: {
			x: 65,
			x2: 30,
			y: showLegend ? 30 : 10,
			y2: 30,
		},
		xAxis: {
			type: 'category',
			data: processLabelTimeArr.value,
			...lineChartStyle.xAxisStyle,
		},
		yAxis: {
			type: 'value',
			splitNumber: 5,
			max: function () {
				if (orderFlag == 1) {
					return 100;
				}
			},
			...lineChartStyle.yAxisStyle,
		},
		series: series,
	});
}

// 业务概况告警请求跳转业务详单查询
function handleAlarmValJump(val: any) {
	console.log(' formData.businessCode');
	let data = JSON.stringify({
		systemId: formData.systemId,
		businessCodeList: [formData.businessCode],
		startTime: formData.startTime,
		endTime: formData.endTime,
		isAlarm: 1,
		completionState: val,
	});
	router.push({
		path: '/business-monitor/monitor-query/business-list',
		query: {
			data,
		},
	});
}
// 业务概况失败请求跳转业务详单查询
function handleFailValJump(val: any) {
	let data = JSON.stringify({
		systemId: formData.systemId,
		businessCodeList: [formData.businessCode],
		startTime: formData.startTime,
		endTime: formData.endTime,
		dealState: '0',
		completionState: val,
	});
	// isWhite('/business-monitor/monitor-query/business-list', {
	// 	data,
	// });
	router.push({
		path: '/business-monitor/monitor-query/business-list',
		query: {
			data,
		},
	});
}
// 点击节点
function clickNode(ev: any) {
	let obj = ev.item.getModel();
	switch (ev.shape.cfg.name) {
		case 'text-value-failCount':
			// 失败请求
			jumpToBaseAlarm(obj, 0);
			break;
		case 'text-value-alarmCount':
			// 告警量
			jumpToBaseAlarm(obj, '');
			break;
		case 'text-value-alarmNum':
			// 告警请求
			jumpToBaseAlarm(obj, '');
			break;
		default:
			break;
	}
}
// 跳转基础告警查询
function jumpToBaseAlarm(obj: any, alarmState: any) {
	obj.stepCode = obj.stepCode || '';
	let data = JSON.stringify({
		systemId: obj.systemId,
		businessCodes: [obj.businessCode],
		stepCodes: [obj.stepCode],
		startTime: formData.startTime,
		endTime: formData.endTime,
		alarmStates: [alarmState],
	});
	router.push({
		path: '/business-monitor/monitor-query/base-alarm-list',
		query: {
			data,
		},
	});
}
//当前用户数跳转用户操作回溯分析
function go2UserOperate(val?: any) {
	router.push({
		path: '/business-monitor/monitor-analysis/user-operate-analysis',
		query: {
			data: JSON.stringify({
				systemId: formData.systemId,
				businessCodes: [formData.businessCode],
				startTime: formData.startTime,
				endTime: formData.endTime,
				userStatus: val === 1 ? 0 : undefined,
			}),
		},
	});
}

// 提包分析
function handlePackageAnalysis(item: any) {
	getConfigKey('apm.datapacket.analysis').then((res) => {
		let ipPort = res.data;
		if (ipPort) {
			let url = 'http://' + ipPort + '/yd-apm-web/api/pktAnalysisController/pktAnalysis.action';
			let userName = btoa('admin');
			let password = btoa('1qazxsw2!@');
			let params = [
				{ name: 'name', value: userName },
				{ name: 'password', value: password },
				{ name: 'beginTime', value: formData.startTime },
				{ name: 'endTime', value: formData.endTime },
				{ name: 'filterType', value: 4 },
				{ name: 'ipStr', value: item.responseIp },
			];
			simulateFormSubmit(url, params, '1', 'get');
		} else {
			proxy?.$message.warning('请前往参数配置页面配置提包分析服务器地址');
		}
	});
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
.nodata-box {
	height: 180px;
	font-size: 18px;
	color: #909399;
	display: flex;
	align-items: center;
	justify-content: center;
}
@mixin title-box {
	display: flex;
	align-items: center;
}
.bg-chart {
	height: 100%;
	width: 100%;
	border-radius: 12px;
	margin-bottom: 10px;
}
.pie-title-box {
	@include title-box;
	height: 12%;
	color: #ffffff;
	font-size: 18px;
	font-weight: bold;
}
.line-title-box-first {
	@include title-box;
	height: 19%;
	color: #ffffff;
	font-size: 16px;
	font-weight: bold;
	padding-top: 28px;
}
.it-title-box {
	@include title-box;
	height: 48px;
	color: #ffffff;
	font-size: 18px;
	font-weight: bold;
}
.line-title-box {
	@include title-box;
	height: 20%;
	color: #ffffff;
	font-size: 16px;
	font-weight: bold;
}
.circle {
	display: inline-block;
	width: 8px;
	height: 8px;
	margin-left: 8px;
	margin-right: 8px;
	background-color: #2beded;
	border-radius: 50%;
	-moz-border-radius: 50%;
	-webkit-border-radius: 50%;
}
.count-text-container {
	height: 100%;
	padding: 15px 20px;
	margin-top: 10px;
	display: flex;
	align-items: center;
	justify-content: center;
	.count-text-box {
		width: 100%;
		height: 100%;
		color: #ffffff;
		border: 1px solid #2beded;
		border-radius: 15px;
		padding: 25px 15px 20px;
		.count-text-row {
			width: 100%;
			height: 100%;
			display: flex;
			align-items: center;
			justify-content: space-between;
			.count-text-cell {
				width: 100%;
				height: 100%;
				display: flex;
				flex-flow: column;
				align-items: center;
				font-size: 14px;
				// flex: 1;
				.count-text-title {
					height: 34%;
					font-size: 16px;
					font-weight: bold;
				}
				.count-text-value {
					height: 33%;
					white-space: nowrap;
				}
				.text-red {
					color: #fe5578;
				}

				.text-yellow {
					color: #ff9a0c;
				}
			}
		}
	}
}
.avg-title-row {
	color: #2beded;
	font-size: 18px;
	font-weight: bold;
	text-align: center;
	height: 50%;
	width: 100%;
	display: flex;
	align-items: center;
}
.avg-value-row {
	color: #ffffff;
	font-size: 16px;
	text-align: center;
	height: 50%;
	width: 100%;
	display: flex;
	align-items: center;
}
.trend-container {
	height: 25%;
	width: 100%;
	padding-bottom: 10px;
}
.step-trend-container-first {
	height: 31%;
	width: 100%;
	padding-bottom: 10px;
}
.step-trend-container {
	height: 23%;
	width: 100%;
	padding-bottom: 10px;
}
.block-title {
	height: 30px;
	color: #ffffff;
	font-size: 18px;
	font-weight: bold;
	display: flex;
	align-items: center;
	margin-bottom: 5px;
}
.userNum {
	color: #2beded;
	font-size: 14px;
	flex: 1;
	margin-right: 5%;
	line-height: 20px;
	.userNum-box {
		width: 50%;
		float: left;
		text-align: center;
		color: #fff;
		font-weight: bold;
	}
	.userNum-text {
		text-decoration: underline;
		cursor: pointer;
	}
	.text-red {
		color: #fe5578;
	}
	.text-blue {
		color: #2beded;
	}
}
.p10 {
	padding: 10px;
}
.mb15 {
	margin-bottom: 15px;
}
</style>
